feat: native OIDC client for per-user SSO (Authentik, Keycloak, any OIDC provider)#1561
feat: native OIDC client for per-user SSO (Authentik, Keycloak, any OIDC provider)#1561aaronckj wants to merge 1 commit into
Conversation
- OidcController: authorization-code flow via jumbojett/openid-connect-php - OidcUserResolver: username mapping, case-insensitive admin break-glass guard, auto-provisioning — unit tested (8 assertions) - EloquentOidcUserRepo: find-or-create Heimdall user from OIDC claims - LoginController: show login page directly; Authentik button at top, local admin form below — no magic URL required - UserController: /userselect redirects to dash when OIDC active + authenticated - layouts/app.blade.php: hide Switch User button when OIDC active - config/services.php: oidc config block (all values from env) - routes/web.php: GET /auth/oidc/login and /auth/oidc/callback - Dockerfile: layer overlay + composer require + php84-sodium onto upstream image - AUTHENTIK_OIDC.md: setup guide and env var reference Tested against Authentik 2026.2.2, PHP 8.4 (Alpine), Laravel 11.45. Upstream pinned to v2.7.6 / lscr.io tag v2.7.6-ls341.
|
This pull request has been automatically marked as stale because it has not had recent activity. This might be due to missing feedback from OP. It will be closed if no further activity occurs. Thank you for your contributions. |
|
Thanks for this — it's a genuinely useful feature and the 1. The
The client library needs to be a real 2. The bundled 3. The OIDC state/nonce session security is unverified — this is the real one. 4. Identity is keyed on Minor: the login button hardcodes "Authentik" and inline styles — a generic "Sign in with SSO" label + CSS class would fit better since the feature is provider-agnostic; and the two Items 1–3 are hard blockers. If you can split out the deployment/Dockerfile bits, add the composer dependency properly, and nail down the session/state handling with a test, I'd be happy to take another look. |
Summary
Adds a native OpenID Connect (OIDC) client to Heimdall so each user can sign in once via an external identity provider (Authentik, Keycloak, Dex, etc.) and land directly on their own dashboard — without a second Heimdall login and without needing a reverse-proxy forward-auth layer.
Closes / relates to: #1445 (request for per-user dashboards with AD/LDAP), and the pattern requested in many forum threads asking for SSO beyond forward-auth headers.
What it does
preferred_usernameis mapped to a Heimdall username. The user is found or auto-provisioned, then logged in viaAuth::login().admin) is hard-blocked from OIDC — case-insensitively, even after username mapping. The local password form remains accessible on/loginbelow the SSO button.OIDC_USERNAME_MAP=src:dst,src2:dst2handles providers that send a differentpreferred_usernamethan the Heimdall username (e.g. an admin account with a different name)./userselectroute redirect to the authenticated user's own dashboard — users can't casually browse other people's dashboards.OIDC_ENABLED=false(the default) means zero behaviour change for existing installations.Files changed
app/Services/OidcUserRepoContract.phpapp/Services/OidcUserResolver.phpapp/Services/EloquentOidcUserRepo.phpapp/Http/Controllers/Auth/OidcController.phpGET /auth/oidc/login+GET /auth/oidc/callbackapp/Http/Controllers/Auth/LoginController.phpapp/Http/Controllers/UserController.php/userselectwhen OIDC + authenticatedconfig/services.phpoidcconfig block, all values from envroutes/web.phpresources/views/auth/login.blade.phpresources/views/layouts/app.blade.phptests/Unit/OidcUserResolverTest.phpDockerfilejumbojett/openid-connect-phpaddedDependencies
One new Composer dependency:
jumbojett/openid-connect-php(^1.0). This is a widely-used, actively maintained OIDC client with no framework coupling. TheDockerfilehandles thecomposer requirestep; for a manual install add it tocomposer.json.Also requires
ext-sodium(for OIDC token crypto) — not present in the linuxserver Alpine image by default. The Dockerfile installsphp84-sodiumvia apk.Configuration
Full setup guide in
AUTHENTIK_OIDC.md(works with any OIDC provider, not just Authentik).Testing
tests/Unit/OidcUserResolverTest.phpcover: username mapping, identity passthrough, admin break-glass (direct + post-mapping + case-insensitive), existing user no-mutate, auto-provision enabled/disabled.OIDC_ENABLED=false(default) was verified to be a no-op — existing installations unaffected.Caveats / known limitations
jumbojett/openid-connect-phpuses PHP's native$_SESSIONfor state/nonce storage. Heimdall'sfilesession driver works correctly alongside it, but this should be noted in documentation for users on other session drivers.Dockerfilepins tolscr.io/linuxserver/heimdall:v2.7.6-ls341as the base — maintainers may want to adjust the build pipeline to produce an official variant instead.